package com.shell.governor.user.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shell.bee.base.exception.UnCheckException;
import com.shell.bee.base.utils.Encryptor;
import com.shell.bee.base.utils.JsonUtil;
import com.shell.bee.base.utils.RandomUtil;
import com.shell.bee.base.utils.SpringContextUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.cache.Cache;
import com.shell.bee.cache.CacheBuilder;
import com.shell.bee.entity.mvc.RetMsg;
import com.shell.bee.file.utils.FileHelper;
import com.shell.bee.persistence.annotation.Pagination;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.bee.persistence.service.impl.PersistentServiceImpl;
import com.shell.bee.sequence.SequenceHelper;
import com.shell.dto.UserAndOrganDto;
import com.shell.feign.ContractTransferFeigh;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.SysDateUtil;
import com.shell.framework.utils.VerifyCodeUtil;
import com.shell.governor.authorization.po.PubRole;
import com.shell.governor.authorization.service.PubRoleService;
import com.shell.governor.modules.message.keyword.SmsCodeKeyword;
import com.shell.governor.modules.message.keyword.SmsResetPasswordKeyWord;
import com.shell.governor.modules.util.MessageSender;
import com.shell.governor.organization.dao.PubOrganDao;
import com.shell.governor.organization.po.PubOrgan;
import com.shell.governor.organization.service.PubOrganService;
import com.shell.governor.organization.vo.PubOrganVo;
import com.shell.governor.security.user.util.SecurityCodeUtil;
import com.shell.governor.user.UserEvent;
import com.shell.governor.user.dao.PubUserDao;
import com.shell.governor.user.dao.PubUserOrganDao;
import com.shell.governor.user.dao.PubUserRoleDao;
import com.shell.governor.user.po.PubUser;
import com.shell.governor.user.po.PubUserExtra;
import com.shell.governor.user.po.PubUserOpt;
import com.shell.governor.user.po.PubUserOrgan;
import com.shell.governor.user.po.PubUserRole;
import com.shell.governor.user.rx.PostUserToEsignSubscriber;
import com.shell.governor.user.rx.SendUserRejectMsgSubscriber;
import com.shell.governor.user.rx.SetFilesSubscriber;
import com.shell.governor.user.rx.SetUserOrganSubscriber;
import com.shell.governor.user.rx.SetUserPasswordSubscriber;
import com.shell.governor.user.rx.SetUserRoleSubscriber;
import com.shell.governor.user.rx.SyncUserToContractSubscriber;
import com.shell.governor.user.rx.UpdateUserOptSubscriber;
import com.shell.governor.user.rx.UpdateUserStateSubscriber;
import com.shell.governor.user.rx.UpdateUserSubscriber;
import com.shell.governor.user.service.PubUserExtraService;
import com.shell.governor.user.service.PubUserService;
import com.shell.governor.user.vo.PubUserVo;
import com.shell.governor.user.vo.UserQueryVo;
import com.shell.properties.GovernorProperties;

import rx.Observable;
import tk.mybatis.mapper.entity.Example;

@Service
public class PubUserServiceImpl extends PersistentServiceImpl<PubUser> implements PubUserService {
	@Autowired
	private PubUserDao pubUserDao;
	@Autowired
	private PubUserRoleDao pubUserRoleDao;
	@Autowired
	private PubUserOrganDao pubUserOrganDao;
	@Autowired
	private PubOrganService pubOrganService;
	@Autowired
	private PubOrganDao pubOrganDao;
	@Autowired
	private PubUserExtraService pubUserExtraService;
	@Autowired
	private GovernorProperties governorProperties;
	@Autowired
	private PubRoleService pubRoleService;
	@Autowired
	private ContractTransferFeigh contractTransferFeigh;
	@Autowired
	private SetUserOrganSubscriber setUserOrganSubscriber;
	@Autowired
	private UpdateUserOptSubscriber updateUserOptSubscriber;
	@Autowired
	private UpdateUserSubscriber updateUserSubscriber;
	@Autowired
	private SetFilesSubscriber setFilesSubscriber;
	@Autowired
	private SetUserRoleSubscriber setUserRoleSubscriber;
	@Autowired
	private UpdateUserStateSubscriber updateUserStateSubscriber;
	@Autowired
	private SendUserRejectMsgSubscriber sendUserRejectMsgSubscriber;
	@Autowired
	private SetUserPasswordSubscriber setUserPasswordSubscriber;
	@Autowired
	private SyncUserToContractSubscriber syncUserToContractSubscriber;
	@Autowired
	private PostUserToEsignSubscriber postUserToEsignSubscriber;
	private static Cache<String, String> CACHE;

	public int saveUser(PubUserVo pubUserVo) {
		int retflag = 1;
		PubUserVo user = new PubUserVo();
		if (StringUtil.emptyAndNull(pubUserVo.getUserId())) {
			user.setUserId(SystemUtil.getUUID());
		} else {
			user.setUserId(pubUserVo.getUserId());
		}
		user.setUserName(pubUserVo.getUserName());
		user.setLoginName(pubUserVo.getLoginName());
		String password = "";
		if (StringUtil.emptyAndNull(pubUserVo.getPassword())) {
			if (!SystemUtil.SystemMode.prod.equals(SystemUtil.getSystemMode())) {
				password = Encryptor.encryptWithMD5(this.governorProperties.getUserDefaultPassword());
			} else {
				password = Encryptor.encryptWithMD5(String.valueOf(RandomUtil.getRandomInt(8)));
			}
		} else {
			password = pubUserVo.getPassword();
		}
		user.setPassword(password);
		user.setCertType(pubUserVo.getCertType());
		user.setCertNo(pubUserVo.getCertNo());
		user.setPhoneNo(pubUserVo.getPhoneNo());
		user.setEmail(pubUserVo.getEmail());

		user.setNote(pubUserVo.getNote());
		if (StringUtil.notEmpty(pubUserVo.getCreatorId())) {
			user.setCreatorId(pubUserVo.getCreatorId());
		} else {
			user.setCreatorId(CommonDataUtil.getUserId());
		}
		user.setCreateTime(SysDateUtil.getSystemDateTime());
		user.setEntId(pubUserVo.getEntId());
		retflag = this.pubUserDao.insert(user);
		if (StringUtil.notEmpty(pubUserVo.getCertFileIds())) {
			FileHelper.setRelateId(pubUserVo.getCertFileIds(), user.getUserId(), "2");
		}
		if (StringUtil.notTrimEmpty(pubUserVo.getOrganId())) {
			if (StringUtil.empty(user.getEntId())) {
				PubOrgan organ = this.pubOrganService.getEntByOrganId(pubUserVo.getOrganId());
				if (null != organ) {
					user.setEntId(organ.getOrganId());
				} else {
					user.setEntId("OG001");
				}
			}
			saveUserOrgan(user.getUserId(), pubUserVo.getOrganId(), user.getEntId(), pubUserVo.getUserOrganValid());
			if (StringUtil.notEmpty(user.getEntId())) {
				PubUserExtra userExtra = new PubUserExtra();
				userExtra.setUserId(user.getUserId());
				userExtra.setEntId(user.getEntId());
				userExtra.setUserState(pubUserVo.getUserState());
				userExtra.setIsDefault("1");
				PubOrgan organ = this.pubOrganService.getEntByOrganId(user.getEntId());
				if ((null != organ) && (StringUtil.notEmpty(organ.getOrganCode()))) {
					userExtra.setInviteCode(organ.getOrganCode() + SequenceHelper.generateCode(
							new StringBuilder().append("IC-").append(organ.getOrganCode()).toString(), 2));
				}
				if (StringUtil.notEmpty(pubUserVo.getAuthFileIds())) {
					userExtra.setAuthFileRlatId(SystemUtil.getUUID());
					FileHelper.setRelateId(pubUserVo.getAuthFileIds(), userExtra.getAuthFileRlatId(), "9");
				}
				if (StringUtil.notEmpty(pubUserVo.getGrpId())) {
					userExtra.setGrpId(pubUserVo.getGrpId());
				}
				this.pubUserExtraService.save(userExtra);
			}
		}
		if ((pubUserVo.getRoles() != null) && (pubUserVo.getRoles().size() > 0)) {
			saveUserRole(pubUserVo, user.getUserId());
		}
		return retflag;
	}

	private void saveUserRole(PubUserVo pubUserVo, String userId) {
		PubUserRole delUr = new PubUserRole();
		delUr.setOrganId(pubUserVo.getEntId());
		delUr.setUserId(userId);
		this.pubUserRoleDao.delete(delUr);
		for (int i = 0; i < pubUserVo.getRoles().size(); i++) {
			PubUserRole ur = new PubUserRole();
			ur.setOrganId(pubUserVo.getEntId());
			ur.setRoleId(((PubRole) pubUserVo.getRoles().get(i)).getRoleId());
			ur.setUserId(userId);
			this.pubUserRoleDao.insert(ur);
		}
	}

	public int updateUser(PubUserVo pubUserVo) {
		int retflag = 0;
		PubUser user = new PubUser();
		user.setUserId(pubUserVo.getUserId());
		user = (PubUser) this.pubUserDao.selectOne(user);
		if (user != null) {
			if (StringUtil.notEmpty(pubUserVo.getUserName())) {
				user.setUserName(pubUserVo.getUserName());
			}
			if (StringUtil.notEmpty(pubUserVo.getLoginName())) {
				user.setLoginName(pubUserVo.getLoginName());
			}
			if (StringUtil.notEmpty(pubUserVo.getCertType())) {
				user.setCertType(pubUserVo.getCertType());
			}
			if (StringUtil.notEmpty(pubUserVo.getCertNo())) {
				user.setCertNo(pubUserVo.getCertNo());
			}
			if (StringUtil.notEmpty(pubUserVo.getPhoneNo())) {
				user.setPhoneNo(pubUserVo.getPhoneNo());
			}
			if (StringUtil.notEmpty(pubUserVo.getEmail())) {
				user.setEmail(pubUserVo.getEmail());
			}
			if (StringUtil.notEmpty(pubUserVo.getNote())) {
				user.setNote(pubUserVo.getNote());
			}
			if (StringUtil.notEmpty(pubUserVo.getUserId())) {
				user.setEditorId(CommonDataUtil.getUserId());
			}
			if (StringUtil.notEmpty(pubUserVo.getPassword())) {
				user.setPassword(pubUserVo.getPassword());
			}
			user.setEditTime(SysDateUtil.getSystemDateTime());

			retflag = this.pubUserDao.updateByPrimaryKeySelective(user);
			if (StringUtil.notEmpty(pubUserVo.getCertFileIds())) {
				FileHelper.setRelateId(pubUserVo.getCertFileIds(), user.getUserId(), "2");
			}
			if (StringUtil.notTrimEmpty(pubUserVo.getOrganId())) {
				updateUserOrgan(user.getUserId(), pubUserVo.getOrganId(), pubUserVo.getUserOrganValid());

				PubUserExtra userExtra = new PubUserExtra();
				userExtra.setUserId(user.getUserId());
				userExtra.setEntId(pubUserVo.getOrganId());

				userExtra = (PubUserExtra) this.pubUserExtraService.selectOne(userExtra);
				if (userExtra == null) {
					if (userExtra == null) {
						userExtra = new PubUserExtra();
					}
					userExtra.setUserId(user.getUserId());
					userExtra.setEntId(pubUserVo.getOrganId());
					if (StringUtil.notEmpty(pubUserVo.getUserState())) {
						userExtra.setUserState(pubUserVo.getUserState());
					}
					PubOrgan organ = this.pubOrganService.getEntByOrganId(pubUserVo.getOrganId());
					if ((null != organ) && (StringUtil.notEmpty(organ.getOrganCode()))) {
						userExtra.setInviteCode(organ.getOrganCode() + SequenceHelper.generateCode(
								new StringBuilder().append("IC-").append(organ.getOrganCode()).toString(), 2));
					}
					if (StringUtil.notEmpty(pubUserVo.getAuthFileIds())) {
						userExtra.setAuthFileRlatId(SystemUtil.getUUID());
						FileHelper.setRelateId(pubUserVo.getAuthFileIds(), userExtra.getAuthFileRlatId(), "9");
					}
					if (StringUtil.notEmpty(pubUserVo.getGrpId())) {
						userExtra.setGrpId(pubUserVo.getGrpId());
					}
					if (!hasDefaultUser(user.getUserId())) {
						cleanDefaultUser(user.getUserId());
						userExtra.setIsDefault("1");
					} else {
						userExtra.setIsDefault("0");
					}
					this.pubUserExtraService.save(userExtra);
				} else {
					if (StringUtil.notEmpty(pubUserVo.getUserState())) {
						userExtra.setUserState(pubUserVo.getUserState());
					}
					if (StringUtil.emptyAndNull(userExtra.getInviteCode())) {
						PubOrgan organ = this.pubOrganService.getEntByOrganId(pubUserVo.getOrganId());
						if ((null != organ) && (StringUtil.notEmpty(organ.getOrganCode()))) {
							userExtra.setInviteCode(organ.getOrganCode() + SequenceHelper.generateCode(
									new StringBuilder().append("IC-").append(organ.getOrganCode()).toString(), 2));
						}
					}
					if (StringUtil.notEmpty(pubUserVo.getAuthFileIds())) {
						if (StringUtil.empty(userExtra.getAuthFileRlatId())) {
							userExtra.setAuthFileRlatId(SystemUtil.getUUID());
						}
						FileHelper.setRelateId(pubUserVo.getAuthFileIds(), userExtra.getAuthFileRlatId(), "9");
					}
					if (StringUtil.notEmpty(pubUserVo.getGrpId())) {
						userExtra.setGrpId(pubUserVo.getGrpId());
					}
					this.pubUserExtraService.updateNotNull(userExtra);
				}
			}
			if ((pubUserVo.getRoles() != null) && (pubUserVo.getRoles().size() > 0)) {
				saveUserRole(pubUserVo, user.getUserId());
			}
		}
		return retflag;
	}

	private void saveUserOrgan(String userId, String organId, String entId, String valid) {
		PubUserOrgan uo = new PubUserOrgan();
		uo.setUserId(userId);
		uo.setDeptId(organId);

		this.pubUserOrganDao.delete(uo);
		uo.setUserId(userId);
		uo.setDeptId(organId);
		uo.setEntId(entId);
		uo.setValid(valid);
		if (StringUtil.emptyAndNull(valid)) {
			uo.setValid("1");
		}
		PubOrgan dept = (PubOrgan) this.pubOrganDao.selectByPrimaryKey(organId);
		PubOrgan ent = (PubOrgan) this.pubOrganDao.selectByPrimaryKey(entId);
		uo.setDeptName(dept.getOrganName());
		uo.setEntName(ent.getOrganName());
		uo.setEntType(ent.getOrganType());

		this.pubUserOrganDao.insert(uo);
	}

	private void updateUserOrgan(String userId, String organId, String valid) {
		PubUserOrgan uo = new PubUserOrgan();
		uo.setUserId(userId);
		uo.setDeptId(organId);
		PubUserOrgan oldUO = (PubUserOrgan) this.pubUserOrganDao.selectOne(uo);
		if (oldUO != null) {
			this.pubUserOrganDao.delete(uo);
			uo.setDeptId(organId);
			uo.setEntId(oldUO.getEntId());
			uo.setValid(valid);
			if (StringUtil.emptyAndNull(valid)) {
				uo.setValid(oldUO.getValid());
			}
		} else {
			uo.setDeptId(organId);
			uo.setEntId(organId);
			uo.setValid(valid);
			if (StringUtil.emptyAndNull(valid)) {
				uo.setValid("1");
			}
		}
		PubOrgan dept = (PubOrgan) this.pubOrganDao.selectByPrimaryKey(organId);
		PubOrgan ent = (PubOrgan) this.pubOrganDao.selectByPrimaryKey(uo.getEntId());
		uo.setDeptName(dept.getOrganName());
		uo.setEntName(ent.getOrganName());
		uo.setEntType(ent.getOrganType());

		this.pubUserOrganDao.insert(uo);
	}

	public String sendVerificationCode(String phoneNumber, String userName) {
		String VerifyCode = VerifyCodeUtil.generateVerifyCode(6, "0123456789");
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("verification_code", VerifyCode);
		params.put("userName", userName);

		return VerifyCode;
	}

	public RetMsg changePhone(PubUser user, String verificationCode, String code) {
		int retflag = 1;
		if (verificationCode.equals(code)) {
			retflag = updateNotNull(user);
			syncUser(user.getUserId());
		} else {
			return new RetMsg("error", "����������������,������.");
		}
		if (retflag == 1) {
			return new RetMsg("success", "��������");
		}
		return new RetMsg("error", "��������");
	}

	public boolean checkCodeUnique(PubUser entity) {
		if (StringUtils.isEmpty(entity.getLoginName())) {
			return true;
		}
		UserQueryVo userVo = new UserQueryVo();
		userVo.setLoginName(entity.getLoginName());
		String[] notState = { "D" };
		userVo.setNotStates(notState);
		if (StringUtil.notEmpty(entity.getUserId())) {
			String[] notUserId = { entity.getUserId() };
			userVo.setNotInUserId(notUserId);
		}
		List<PubUserVo> users = queryUser(userVo);

		return users.size() <= 0;
	}

	public RetMsg deleteUser(PubUser user, String entId) {
		PubUserExtra userExtra = new PubUserExtra();
		userExtra.setUserId(user.getUserId());
		userExtra.setEntId(entId);
		userExtra.setUserState("D");
		int update_count = 0;
		update_count = this.pubUserExtraService.updateNotNull(userExtra);
		if (update_count > 0) {
			return new RetMsg("success", "��������!");
		}
		return new RetMsg("error", "����������");
	}

	public int updateState(String userState, String userId, String entId) {
		return this.pubUserDao.updateState(userState, userId, entId);
	}

	public PubUserVo selectUser(String id) {
		PubUserVo param = new PubUserVo();
		param.setUserId(id);
		List<PubUserVo> users = this.pubUserDao.selectUsers(param);
		if (users.size() > 0) {
			return (PubUserVo) users.get(0);
		}
		return null;
	}

	@Pagination
	public List<PubUserVo> selectUsersByPage(PageLimit limit, PubUserVo user) {
		if (StringUtil.notEmpty(user.getUserName())) {
			user.setUserName(StringUtil.getParameterLike(user.getUserName()));
		}
		if (StringUtil.notEmpty(user.getPhoneNo())) {
			user.setPhoneNo(StringUtil.getParameterLike(user.getPhoneNo()));
		}
		if (StringUtil.notEmpty(user.getLoginName())) {
			user.setLoginName(StringUtil.getParameterLike(user.getLoginName()));
		}
		if (StringUtil.notEmpty(user.getSearchVuale())) {
			user.setSearchVuale(StringUtil.getParameterLike(user.getSearchVuale()));
		}
		user.setOrganType("ROOT");
		return this.pubUserDao.selectUsers(user);
	}

	public RetMsg resetUserPassword(String userId) {
		PubUser u = (PubUser) this.pubUserDao.selectByPrimaryKey(userId);
		String newPassword;
		if (!SystemUtil.SystemMode.prod.equals(SystemUtil.getSystemMode())) {
			newPassword = this.governorProperties.getUserDefaultPassword();
		} else {
			newPassword = String.valueOf(RandomUtil.getRandomInt(8));
		}
		u.setPassword(Encryptor.encryptWithMD5(newPassword));
		if (this.pubUserDao.updateByPrimaryKey(u) > 0) {
			SmsResetPasswordKeyWord keyword = new SmsResetPasswordKeyWord();
			keyword.setNewPassword(newPassword);
			MessageSender.sendMessageToPhone(u.getPhoneNo(), CommonDataUtil.getCurEntId(), "MT00129", keyword);

			return new RetMsg("success", false, "������������" + u.getLoginName() + ",������:" + newPassword);
		}
		return new RetMsg("error", false, "��������������");
	}

	public int modifyUserPassword(String userId, String newPassword, String oldPassword) {
		int returnValue = 0;
		Example example = new Example(PubUser.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("userId", userId);
		if (!StringUtil.emptyAndNull(oldPassword)) {
			criteria.andEqualTo("password", oldPassword);
		}
		List<PubUser> users = this.pubUserDao.selectByExample(example);
		if (users.size() > 0) {
			PubUser u = (PubUser) users.get(0);
			u.setPassword(newPassword);
			returnValue = this.pubUserDao.updateByPrimaryKeySelective(u);
		}
		return returnValue;
	}

	public PubUserVo findUserByLoginName(String loginName) {
		UserQueryVo query = new UserQueryVo();
		query.setLoginName(loginName);
		String[] states = { "E", "F", "U" };
		query.setStates(states);

		List<PubUserVo> users = queryUser(query);
		if ((users == null) || (users.size() == 0)) {
			query = new UserQueryVo();
			query.setPhoneNo(loginName);
			query.setStates(states);
			users = queryUser(query);
		}
		if ((users != null) && (users.size() > 0)) {
			for (PubUserVo u : users) {
				if ("1".equals(u.getIsDefault())) {
					return u;
				}
			}
			return (PubUserVo) users.get(0);
		}
		return null;
	}

	public List<PubUser> selectUsersByRoleCodes(String organId, String... roleCodes) {
		return this.pubUserDao.selectUsersByRoleCodes(organId, roleCodes);
	}

	public List<PubUser> selectUsersByUserNames(String... userNames) {
		return this.pubUserDao.selectUsersByUserNames(userNames);
	}

	public Boolean existUserWithRole(String userId, String roleCode) {
		List<PubUser> fus = this.pubUserDao.selectUserByIdRole(userId, roleCode);
		Boolean exist = Boolean.valueOf(false);
		if ((null != fus) && (fus.size() > 0)) {
			exist = Boolean.valueOf(true);
		}
		return exist;
	}

	public RetMsg modifyPasswordByLoginNameOrPhoneNo(String loginName, String phoneNo, String newPassword,
			String srecurityCode) {
		if (StringUtil.emptyAndNull(SecurityCodeUtil.getCode(srecurityCode))) {
			return new RetMsg("error", "��������������������������������������");
		}
		if (!SecurityCodeUtil.checkCode(srecurityCode)) {
			return new RetMsg("error", "������������������������������������");
		}
		UserQueryVo user = new UserQueryVo();
		user.setLoginName(loginName);
		if ((StringUtil.emptyAndNull(loginName)) && (!StringUtil.emptyAndNull(phoneNo))) {
			user.setPhoneNo(phoneNo);
		} else {
			user.setLoginName(loginName);
		}
		String[] notState = { "D" };
		user.setNotStates(notState);
		List<PubUserVo> users = this.pubUserDao.queryUser(user);
		if ((users == null) || (users.size() == 0)) {
			return new RetMsg("error", "����������");
		}
		int value = modifyUserPassword(((PubUserVo) users.get(0)).getUserId(), newPassword,
				((PubUserVo) users.get(0)).getPassword());
		if (value > 0) {
			return new RetMsg("success", "��������������");
		}
		return new RetMsg("error", "��������������������������������");
	}

	public boolean checkPhoneNoUnique(String userId, String loginName, String phoneNo) {
		UserQueryVo userVo = new UserQueryVo();
		userVo.setNotStates(new String[] { "D" });
		userVo.setPhoneNo(phoneNo);
		if (!StringUtil.emptyAndNull(userId)) {
			String[] notUserIds = { userId };
			userVo.setNotInUserId(notUserIds);
		}
		if (!StringUtil.emptyAndNull(loginName)) {
			String[] notLoginNames = { loginName };
			userVo.setNotLoginNames(notLoginNames);
		}
		List<PubUserVo> list = queryUser(userVo);
		if ((list != null) && (list.size() > 0)) {
			return false;
		}
		return true;
	}

	public List<PubUser> selectUserByRoleId(String roleId) {
		if (StringUtil.emptyAndNull(roleId)) {
			return new ArrayList<PubUser>();
		}
		return this.pubUserDao.selectUserByRoleId(roleId);
	}

	public List<PubUserVo> selectUserVoByCode(String organCode, String userCode) {
		if ((StringUtil.emptyAndNull(userCode)) || (StringUtil.emptyAndNull(organCode))) {
			return null;
		}
		return this.pubUserDao.selectUserVoByCode(organCode, userCode);
	}

	public List<PubUserVo> selectUserVoByOrgan(String organId) {
		if (StringUtil.emptyAndNull(organId)) {
			return null;
		}
		PubUserVo vo = new PubUserVo();
		vo.setEntId(organId);
		return this.pubUserDao.selectEntUsersByPage(vo);
	}

	@Pagination
	public List<PubUserVo> selectEntUsersByPage(PageLimit limit, PubUserVo user) {
		if (StringUtil.notEmpty(user.getUserName())) {
			user.setUserName(StringUtil.getParameterLike(user.getUserName()));
		}
		if (StringUtil.notEmpty(user.getLoginName())) {
			user.setLoginName(StringUtil.getParameterLike(user.getLoginName()));
		}
		if (StringUtil.notEmpty(user.getSearchVuale())) {
			user.setSearchVuale(StringUtil.getParameterLike(user.getSearchVuale()));
		}
		user.setOrganType("ROOT");
		user.setEntId(CommonDataUtil.getCurEntId());
		return this.pubUserDao.selectEntUsersByPage(user);
	}

	public List<PubUserOrgan> selectUserByOrganId(List<Object> userIds, String organId) {
		Example example = new Example(PubUserOrgan.class);
		Example.Criteria criteria = example.createCriteria();
		if (!StringUtil.emptyAndNull(organId)) {
			criteria.andEqualTo("organId", organId);
		}
		if ((userIds != null) && (userIds.size() > 0)) {
			criteria.andIn("userId", userIds);
		}
		return this.pubUserOrganDao.selectByExample(example);
	}

	public List<String> selectByResCodeAndOrgId(String organId, String... resCode) {
		return this.pubUserDao.selectByResCodeAndOrgId(organId, resCode);
	}

	public int updateLoginName(PubUserVo pubUserVo) {
		int result = 0;
		PubUser user = new PubUser();
		user.setUserId(pubUserVo.getUserId());
		user.setLoginName(pubUserVo.getLoginName());
		result = this.pubUserDao.updateByPrimaryKeySelective(user);
		syncUser(user.getUserId());
		return result;
	}

	public int updateUsersStateByCreatorId(String creatorId, String userState) {
		return this.pubUserDao.updateUsersStateByCreatorId(creatorId, userState);
	}

	public int batchSaveUserOrgan(List<PubUserOrgan> userOrgans) {
		return this.pubUserOrganDao.batchSaveUserOrgan(userOrgans);
	}

	public List<PubUserVo> selectUserByRoleCodeAndEntId(String entId, String roleCode) {
		return this.pubUserDao.selectUserByRoleCodeAndEntId(entId, roleCode);
	}

	public void saveOrUpdateUserAndOrgan(UserAndOrganDto userAndOrganDto) {
		PubOrganVo organVo = userAndOrganDto.getOrgan();
		if (organVo != null) {
			int result = this.pubOrganService.saveOrUpdateOrganRecord(organVo);
			if (result < 1) {
				throw new UnCheckException("����/������������������");
			}
		}
		List<PubUserVo> userVos = userAndOrganDto.getUsers();
		if (userVos != null) {
			for (PubUserVo userVo : userVos) {
				PubUser user = null;
				if (!StringUtil.empty(userVo.getUserId())) {
					user = (PubUser) selectByKey(userVo.getUserId());
				}
				int result = 0;
				if (user == null) {
					result = saveUser(userVo);
				} else {
					result = updateUser(userVo);
				}
				if (result < 1) {
					throw new UnCheckException("����/����������������");
				}
				if (("on".equals(SpringContextUtil.getProperty("contract.switch"))) && (userVo.isNeedSync())) {
					String userJson = null;
					try {
						userJson = JsonUtil.toJson(userVo);
					} catch (Exception e) {
						throw new UnCheckException("user json ��������");
					}
					this.contractTransferFeigh.personalUserSync(userJson);
					if ((userVo.getRoles() != null) && (userVo.getRoles().size() > 0)) {
						this.contractTransferFeigh.signerActiveSyncByUser(userVo.getEntId(), userJson);
					}
				}
			}
		}
	}

	private void syncUser(String userId) {
		if ("on".equals(SpringContextUtil.getProperty("contract.switch"))) {
			this.contractTransferFeigh.personalUserSyncById(userId);
			List<PubRole> roles = this.pubRoleService.selectRoleForUser(userId, null);
			if (roles.size() > 0) {
				this.contractTransferFeigh.signerActiveSync(CommonDataUtil.getCurEntId(), userId);
			}
		}
	}

	public List<PubUserVo> selectAllUserForEnt(String entId) {
		return this.pubUserDao.selectAllUserForEnt(entId);
	}

	public boolean addUserForEnt(PubUserVo userVo) {
		PubUserOpt userOpt = new PubUserOpt();
		userOpt.setBizCode("0");
		userOpt.setCurState("0");
		userOpt.setNextState("1");

		UserEvent event = new UserEvent();
		event.setUserOpt(userOpt);
		event.setUserVo(userVo);

		Observable<UserEvent> observers = Observable.just(event);

		observers.subscribe(this.updateUserSubscriber);
		observers.subscribe(this.postUserToEsignSubscriber);
		observers.subscribe(this.setUserOrganSubscriber);
		observers.subscribe(this.setFilesSubscriber);
		observers.subscribe(this.setUserRoleSubscriber);
		observers.subscribe(this.updateUserOptSubscriber);
		observers.subscribe(this.setUserPasswordSubscriber);
		observers.subscribe(this.syncUserToContractSubscriber);

		return event.isNeedApprover();
	}

	@Pagination
	public List<PubUserVo> selectUserForApr(PageLimit limit, UserQueryVo userVo) {
		return this.pubUserDao.selectUserForApr(userVo);
	}

	public void firstTrialPass(PubUserOpt userOpt) {
		userOpt.setBizCode("1");
		userOpt.setCurState("1");
		userOpt.setNextState("E");

		UserEvent event = new UserEvent();
		event.setUserOpt(userOpt);

		Observable<UserEvent> observers = Observable.just(event);

		observers.subscribe(this.updateUserStateSubscriber);
		observers.subscribe(this.updateUserOptSubscriber);
	}

	public void firstTrialReject(PubUserOpt userOpt) {
		userOpt.setBizCode("1");
		userOpt.setCurState("2");
		userOpt.setNextState("1");

		UserEvent event = new UserEvent();
		event.setUserOpt(userOpt);

		Observable<UserEvent> observers = Observable.just(event);

		observers.subscribe(this.updateUserStateSubscriber);
		observers.subscribe(this.updateUserOptSubscriber);
		observers.subscribe(this.sendUserRejectMsgSubscriber);
	}

	public void lastTrialPass(PubUserOpt userOpt) {
		userOpt.setBizCode("2");
		userOpt.setCurState("E");
		userOpt.setNextState("E");

		UserEvent event = new UserEvent();
		event.setUserOpt(userOpt);

		Observable<UserEvent> observers = Observable.just(event);

		observers.subscribe(this.updateUserStateSubscriber);
		observers.subscribe(this.updateUserOptSubscriber);
		observers.subscribe(this.setUserPasswordSubscriber);
		observers.subscribe(this.syncUserToContractSubscriber);
	}

	public void lastTrialReject(PubUserOpt userOpt) {
		userOpt.setBizCode("2");
		userOpt.setCurState("3");
		userOpt.setNextState("0");

		UserEvent event = new UserEvent();
		event.setUserOpt(userOpt);

		Observable<UserEvent> observers = Observable.just(event);

		observers.subscribe(this.updateUserStateSubscriber);
		observers.subscribe(this.updateUserOptSubscriber);
	}

	public List<PubUserVo> queryUser(UserQueryVo userVo) {
		return this.pubUserDao.queryUser(userVo);
	}

	public void updateUserForEnt(PubUserVo userVo) {
		PubUser user = selectUser(userVo.getUserId());

		BeanUtils.copyProperties(userVo, user);
		UserEvent event = new UserEvent();
		event.setUser(user);

		Observable<UserEvent> observers = Observable.just(event);
		observers.subscribe(this.postUserToEsignSubscriber);

		this.pubUserDao.updateByPrimaryKeySelective(user);
	}

	public int uploadUserInfo(PubUser user, String msgVerifyCode) {
		if (!StringUtil.emptyAndNull(user.getUserId())) {
			if (StringUtil.emptyAndNull(msgVerifyCode)) {
				return updateNotNull(user);
			}
			if (CACHE == null) {
				return 2;
			}
			String cacheSmsCode = (String) CACHE.get(user.getPhoneNo());
			if (StringUtil.emptyAndNull(cacheSmsCode)) {
				return 3;
			}
			if (!cacheSmsCode.equals(msgVerifyCode)) {
				return 4;
			}
			return updateNotNull(user);
		}
		return 0;
	}

	public String sendSMS(String phoneNo) {
		if (CACHE == null) {
			CACHE = CacheBuilder.newBuilder().build();
		}
		String smsCode = (String) CACHE.get(phoneNo);
		if (StringUtil.emptyAndNull(smsCode)) {
			smsCode = VerifyCodeUtil.generateVerifyCode(4, "0123456789");
			CACHE.put(phoneNo, smsCode, 300);
		}
		String template = "MT02209";

		SmsCodeKeyword keyword = new SmsCodeKeyword();
		keyword.setPhoneCode(smsCode);
		try {
			MessageSender.sendMessageToPhone(phoneNo, "", template, keyword);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return smsCode;
	}

	public boolean hasDefaultUser(String userId) {
		PubUserExtra userExtra = new PubUserExtra();
		userExtra.setUserId(userId);
		userExtra.setUserState("E");
		userExtra.setIsDefault("1");
		List<PubUserExtra> ues = this.pubUserExtraService.selectByEntity(userExtra);
		if ((ues != null) && (ues.size() > 0)) {
			return true;
		}
		return false;
	}

	public void cleanDefaultUser(String userId) {
		PubUserExtra userExtra = new PubUserExtra();
		userExtra.setUserId(userId);
		List<PubUserExtra> ues = this.pubUserExtraService.selectByEntity(userExtra);
		for (PubUserExtra ue : ues) {
			ue.setIsDefault("0");
			this.pubUserExtraService.updateAll(ue);
		}
	}

	public void setDefault(String userId, String entId) {
		cleanDefaultUser(userId);
		PubUserExtra userExtra = new PubUserExtra();
		userExtra.setEntId(entId);
		userExtra.setUserId(userId);
		userExtra.setIsDefault("1");
		this.pubUserExtraService.updateNotNull(userExtra);
	}

	public void updatePasswordExcludeAdmin(String password) {
		this.pubUserDao.updatePasswordExcludeAdmin(password);
	}

	public PubUser selectUserByPhone(String userPhone) {
		List<PubUser> list = this.pubUserDao.selectUserByPhone(userPhone);
		if ((list != null) && (list.size() > 0)) {
			return (PubUser) list.get(0);
		}
		return null;
	}

	public PubUser selectUserByIdCard(String certNo) {
		Example example = new Example(PubUser.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("certNo", certNo);
		criteria.andEqualTo("userId", CommonDataUtil.getUserId());
		List<PubUser> list = selectByExample(example);
		if ((list != null) && (list.size() > 0)) {
			return (PubUser) list.get(0);
		}
		return null;
	}
}
